/**
 * 上海中赢金融信息服务有限公司
 * Copyright (c) 2017-2027 Chinazyjr,Inc.All Rights Reserved.
 */

package com.sys.midware.assist.utils.number;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import org.apache.commons.lang3.RandomStringUtils;

/**
 * <b>ClassName:</b> NumberUtils.java <br/>
 * <b>Description:</b> TODO <br/>
 * <b>Date:</b>     2015年10月19日 下午1:55:33<br/> 
 * @author   mobing
 * @version  	 
 */
public class NumberUtil {
    /**
     * <p>Convert a <code>String</code> to an <code>int</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toInt(null, 1) = 1
     *   NumberUtils.toInt("", 1)   = 1
     *   NumberUtils.toInt("1", 0)  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @param defaultValue  the default value
     * @return the int represented by the string, or the default if conversion fails
     * @since 2.1
     */
    public static int toInt(String str, int defaultValue) {
        if(str == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }
    
    /**
     * <p>Convert a <code>String</code> to an <code>int</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toInt(null) = 0
     *   NumberUtils.toInt("")   = 0
     *   NumberUtils.toInt("1")  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @return the int represented by the string, or <code>zero</code> if
     *  conversion fails
     * @since 2.1
     */
    public static int toInt(String str) {
        return toInt(str, 0);
    }
    
    
    /**
     * <p>Convert a <code>String</code> to a <code>long</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toLong(null) = 0L
     *   NumberUtils.toLong("")   = 0L
     *   NumberUtils.toLong("1")  = 1L
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @return the long represented by the string, or <code>0</code> if
     *  conversion fails
     * @since 2.1
     */
    public static long toLong(String str) {
        return toLong(str, 0L);
    }

    /**
     * <p>Convert a <code>String</code> to a <code>long</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toLong(null, 1L) = 1L
     *   NumberUtils.toLong("", 1L)   = 1L
     *   NumberUtils.toLong("1", 0L)  = 1L
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @param defaultValue  the default value
     * @return the long represented by the string, or the default if conversion fails
     * @since 2.1
     */
    public static long toLong(String str, long defaultValue) {
        if (str == null) {
            return defaultValue;
        }
        try {
            return Long.parseLong(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }
    
    /**
     * <p>Convert a <code>String</code> to a <code>float</code>, returning
     * <code>0.0f</code> if the conversion fails.</p>
     *
     * <p>If the string <code>str</code> is <code>null</code>,
     * <code>0.0f</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toFloat(null)   = 0.0f
     *   NumberUtils.toFloat("")     = 0.0f
     *   NumberUtils.toFloat("1.5")  = 1.5f
     * </pre>
     *
     * @param str the string to convert, may be <code>null</code>
     * @return the float represented by the string, or <code>0.0f</code>
     *  if conversion fails
     * @since 2.1
     */
    public static float toFloat(String str) {
        return toFloat(str, 0.0f);
    }

    /**
     * <p>Convert a <code>String</code> to a <code>float</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string <code>str</code> is <code>null</code>, the default
     * value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toFloat(null, 1.1f)   = 1.0f
     *   NumberUtils.toFloat("", 1.1f)     = 1.1f
     *   NumberUtils.toFloat("1.5", 0.0f)  = 1.5f
     * </pre>
     *
     * @param str the string to convert, may be <code>null</code>
     * @param defaultValue the default value
     * @return the float represented by the string, or defaultValue
     *  if conversion fails
     * @since 2.1
     */
    public static float toFloat(String str, float defaultValue) {
      if (str == null) {
          return defaultValue;
      }     
      try {
          return Float.parseFloat(str);
      } catch (NumberFormatException nfe) {
          return defaultValue;
      }
    }

    /**
     * <p>Convert a <code>String</code> to a <code>double</code>, returning
     * <code>0.0d</code> if the conversion fails.</p>
     *
     * <p>If the string <code>str</code> is <code>null</code>,
     * <code>0.0d</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toDouble(null)   = 0.0d
     *   NumberUtils.toDouble("")     = 0.0d
     *   NumberUtils.toDouble("1.5")  = 1.5d
     * </pre>
     *
     * @param str the string to convert, may be <code>null</code>
     * @return the double represented by the string, or <code>0.0d</code>
     *  if conversion fails
     * @since 2.1
     */
    public static double toDouble(String str) {
        return toDouble(str, 0.0d);
    }

    /**
     * <p>Convert a <code>String</code> to a <code>double</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string <code>str</code> is <code>null</code>, the default
     * value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toDouble(null, 1.1d)   = 1.1d
     *   NumberUtils.toDouble("", 1.1d)     = 1.1d
     *   NumberUtils.toDouble("1.5", 0.0d)  = 1.5d
     * </pre>
     *
     * @param str the string to convert, may be <code>null</code>
     * @param defaultValue the default value
     * @return the double represented by the string, or defaultValue
     *  if conversion fails
     * @since 2.1
     */
    public static double toDouble(String str, double defaultValue) {
      if (str == null) {
          return defaultValue;
      }
      try {
          return Double.parseDouble(str);
      } catch (NumberFormatException nfe) {
          return defaultValue;
      }
    }
    
    /**
     * <p>Convert a <code>String</code> to a <code>byte</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toByte(null) = 0
     *   NumberUtils.toByte("")   = 0
     *   NumberUtils.toByte("1")  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @return the byte represented by the string, or <code>zero</code> if
     *  conversion fails
     * @since 2.5
     */
    public static byte toByte(String str) {
        return toByte(str, (byte) 0);
    }

    /**
     * <p>Convert a <code>String</code> to a <code>byte</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toByte(null, 1) = 1
     *   NumberUtils.toByte("", 1)   = 1
     *   NumberUtils.toByte("1", 0)  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @param defaultValue  the default value
     * @return the byte represented by the string, or the default if conversion fails
     * @since 2.5
     */
    public static byte toByte(String str, byte defaultValue) {
        if(str == null) {
            return defaultValue;
        }
        try {
            return Byte.parseByte(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }

    /**
     * <p>Convert a <code>String</code> to a <code>short</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtils.toShort(null) = 0
     *   NumberUtils.toShort("")   = 0
     *   NumberUtils.toShort("1")  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @return the short represented by the string, or <code>zero</code> if
     *  conversion fails
     * @since 2.5
     */
    public static short toShort(String str) {
        return toShort(str, (short) 0);
    }

    /**
     * <p>Convert a <code>String</code> to an <code>short</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtils.toShort(null, 1) = 1
     *   NumberUtils.toShort("", 1)   = 1
     *   NumberUtils.toShort("1", 0)  = 1
     * </pre>
     *
     * @param str  the string to convert, may be null
     * @param defaultValue  the default value
     * @return the short represented by the string, or the default if conversion fails
     * @since 2.5
     */
    public static short toShort(String str, short defaultValue) {
        if(str == null) {
            return defaultValue;
        }
        try {
            return Short.parseShort(str);
        } catch (NumberFormatException nfe) {
            return defaultValue;
        }
    }
    
    private static final int DEF_DIV_SCALE = 2;  
    /** 
     * 判断字符串是否为数字 
     * @param num 
     * @return 
     */  
    public static boolean isNumberic(String num){  
        return (null == num || num.length() <= 0 || num.matches("\\d{1,}")) ? true : false;  
    }  
      
    /** 
     * @param parm 
     * @return 返回指定位数随机数 
     */  
    public static String randomNumber(int parm)  
    {  
        return RandomStringUtils.randomNumeric(parm);  
    }  
  
    /** 
     * * 两个Double数相加 * 
     *  
     * @param v1 * 
     * @param v2 * 
     * @return Double 
     */  
    public static Double add(Double v1, Double v2) {  
        BigDecimal b1 = new BigDecimal(v1.toString());  
        BigDecimal b2 = new BigDecimal(v2.toString());  
        return new Double(b1.add(b2).doubleValue());  
    }  
  
    /** 
     * * 两个Double数相减 * 
     *  
     * @param v1 * 
     * @param v2 * 
     * @return Double 
     */  
    public static Double sub(Double v1, Double v2) {  
        BigDecimal b1 = new BigDecimal(v1.toString());  
        BigDecimal b2 = new BigDecimal(v2.toString());  
        return new Double(b1.subtract(b2).doubleValue());  
    }  
  
    /** 
     * * 两个Double数相乘 * 
     *  
     * @param v1 * 
     * @param v2 * 
     * @return Double 
     */  
    public static Double mul(Double v1, Double v2) {  
        BigDecimal b1 = new BigDecimal(v1.toString());  
        BigDecimal b2 = new BigDecimal(v2.toString());  
        return new Double(b1.multiply(b2).doubleValue());  
    }  
  
    /** 
     * * 两个Double数相除 * 
     *  
     * @param v1 * 
     * @param v2 * 
     * @return Double 
     */  
    public static Double div(Double v1, Double v2) {  
        BigDecimal b1 = new BigDecimal(v1.toString());  
        BigDecimal b2 = new BigDecimal(v2.toString());  
        return new Double(b1  
                .divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP)  
                .doubleValue());  
    }  
  
    /** 
     * * 两个Double数相除，并保留scale位小数 * 
     *  
     * @param v1 * 
     * @param v2 * 
     * @param scale * 
     * @return Double 
     */  
    public static Double div(Double v1, Double v2, int scale) {  
        if (scale < 0) {  
            throw new IllegalArgumentException(  
                    "The scale must be a positive integer or zero");  
        }  
        BigDecimal b1 = new BigDecimal(v1.toString());  
        BigDecimal b2 = new BigDecimal(v2.toString());  
        return new Double(b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)  
                .doubleValue());  
    }  
      
    /** 
     * @param v1 
     * @return 返回指定Double的负数 
     */  
    public static Double neg(Double v1) {  
        return sub(new Double(0),v1);  
    }  
    
    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static Float roundFloat(Float v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).floatValue();
    }
    /**
     * 取整。
     * @param v 需要四舍五入的数字
     * @return 四舍五入后的结果
     */
    public static Integer round(double v){
        return Integer.valueOf(new DecimalFormat("0").format(v));
    }
    /**
     * 取整。
     * @param v 需要四舍五入的数字
     * @return 四舍五入后的结果
     */
    public static Integer round(String v){
        double doubleV=0;
        if(v !=null){
            doubleV = Double.valueOf(v);
        }
        
        NumberFormat format= NumberFormat.getInstance();
        format.setMaximumFractionDigits(0);
       return Integer.valueOf(format.format((doubleV*10+0.5)/10));
//      DecimalFormat df=new DecimalFormat("0");
//        return Integer.valueOf(df.format(doubleV));
    }
    
    /**
     * 取整。
     */
    public static Integer ceil(double v){
        return Integer.valueOf(new DecimalFormat("0").format(Math.floor(v)));
    }
    /**
     * 取整。
     */
    public static Integer ceil(String v){
        double doubleV=0;
        if(v !=null){
            doubleV = Double.valueOf(v);
        }
        return Integer.valueOf(new DecimalFormat("0").format(Math.floor(doubleV)));
    }
    /**
     * 获取人民币类型字符串
     */
    public static String getCurrencyFormat(double val){
         NumberFormat n = NumberFormat.getCurrencyInstance();  
         String outStr = null;  
         try {  
              outStr = n.format(val);  
         } catch (Exception e) {  
             e.printStackTrace();  
         }  
         return outStr;  
    }
    
    /**
     * 将货币格式的值变为数值类型
     */
    public static Double getDouble4Currency(String val){
        if(val!=null){
            val.replaceAll(",", "");
            return Double.valueOf(val);
        }
         return null;  
    }
}

